﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Cloo;
using RayDen.Library.Components.SystemComponents;

namespace RayDen.RayEngine.IntersectionEngines.OpenCL {
    public class  ClDeviceContext {
        public string KernelSrc { get; set; }

        public ComputePlatform platform;
        public ComputeDevice device;
        public ComputeContext context;
        public ComputeContextPropertyList properties;
        public ComputeProgram program;
        public ComputeCommandQueue commands;
        public ComputeKernel kernel;
        public Dictionary<string,ComputeKernel> kernels;


        protected void ReadFromFile(string fileName) {
            using (TextReader reader = new StreamReader(fileName)) {
                this.KernelSrc = reader.ReadToEnd();
            }
        }

        public virtual void Initialize() {
            platform = ComputePlatform.Platforms[0];
            device = platform.Devices[0];

            properties = new ComputeContextPropertyList(platform);
            context = new ComputeContext(new[] { device }, properties, null, IntPtr.Zero);
            program = new ComputeProgram(context, KernelSrc);
        }

        public virtual void SetParams(params object[] parameters) {
        }

        public void SetupDevice(params string[] kernelNames) {
            try {
                this.program.Build(new[] { device }, string.Empty, null, IntPtr.Zero);
            }
            catch (Exception) {
                Tracer.TraceLine(this.program.GetBuildLog(ComputePlatform.Platforms[0].Devices[0]));
                throw;
            }
            if (kernelNames.Length > 1)
            {
                kernels = program.CreateAllKernels().ToDictionary(item => item.FunctionName);
            }
            else
            {
                kernel = program.CreateKernel(kernelNames[0]);                
            }
            commands = new ComputeCommandQueue(context, context.Devices[0], ComputeCommandQueueFlags.None);
        }

        public virtual void RunKernel() { }
    }
}
